<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

$Id$

-%>
<%
    local ubus = require "luci.ubus"
    local portNum = ubus.getPortNum()
    local cleIdx = luci.http.formvalue("clear")
    if cleIdx then
        local cleVal = luci.json.decode(cleIdx)
        local idx = string.format("idx-%d",tonumber(cleVal.idx))
        local clearStatus = ubus.clear_args("port_aggr", "port_aggr_clear", idx)
        luci.http.prepare_content("application/json")
        luci.http.write_json(clearStatus)
        return
    end
   
    local loadModeVal =  luci.http.formvalue("setLoad")
    if loadModeVal then
        
        local sndLoadMode = {["load_balance"] = loadModeVal}
        local sndLoadStatus = ubus.set_args("port_aggr", "port_aggr_set", sndLoadMode, 2)
        
        luci.http.prepare_content("application/json")
        luci.http.write_json(sndLoadStatus)
        
        return
    end

    local selectVal =  luci.http.formvalue("modedisable")
    if selectVal then
        
        local dMode = {["mode_select"] = selectVal}
        local dModeStatus = ubus.set_args("port_aggr", "port_aggr_set", dMode, 2)
        
        luci.http.prepare_content("application/json")
        luci.http.write_json(dModeStatus)
        
        return
    end

    local rcvJson = luci.http.formvalue("param")
    if rcvJson then
        local setAggrJson = luci.json.decode(rcvJson)
        local pVal = string.format("idx-%s",setAggrJson.idx)
        local setAggrSnd={[pVal]={{["channel_id"] = setAggrJson.channel_id},{["channel_member"] =setAggrJson.channel_member}}} 
        
        local setAggrStatus = ubus.set_args("port_aggr","port_aggr_set",setAggrSnd,2)
        luci.http.prepare_content("application/json")
        luci.http.write_json(setAggrStatus)

        return
    end
   
    local typeStatus = ubus.getPortType(portNum) 

    local modeStatus = ubus.get_args("port_aggr", "port_aggr_get", {"mode_select"}, 2)
    local modeVal = modeStatus["ret"][1].mode_select

    local loadVal = {["load_balance"]="0",["channel_num"]="0"}
    local channel = {}
    local chan = {"channel_id","channel_member"}
    local balVal = "1" 
    local chanVal = "0"
    local status ={}
    if (modeVal == "2") then
        local loadStatus = ubus.get_args("port_aggr", "port_aggr_get", {"load_balance","channel_num"}, 2)
        balVal = loadStatus["ret"][1].load_balance
        chanVal = loadStatus["ret"][2].channel_num
        if chanVal ~=nil and tonumber(chanVal) > 0  then
            for i=1,tonumber(chanVal) do
                local pa = string.format("idx-%d",i)
                channel[i]={[pa] = chan}
            end
            status = ubus.get_args("port_aggr", "port_aggr_get", channel, 1)

        end 
    end

%>

<%+header%>

<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">
//字节串 字节数
var OCTET_NUM = Math.ceil(<%=portNum%>/8);

//对数值高低换位
function shift_fun(len,data)
{
    var i;
    var tmp = 0;

    for(i=0;i<len;i++)
    { 
        tmp=((data>>i)&0x01)|tmp; 
        if(i<len-1) 
            tmp=tmp<<1; 
    } 
    return tmp;  
} 
//模式选择隐藏
function modeSelect(){
    var val = document.getElementById("trunkMode").value;
    if(val == "1"){//disable
        if(confirm("<%:are you sure you want to switch configuration?%>")){
            //异步提交数据
            XHR.get('<%=REQUEST_URI%>',{"modedisable": "1"}, 
                    function(x,rv) {
                        //  alert(JSON.stringify(rv));
                        if(rv.ret == "-1"){
                            alert("<%:switch failure%>");
                            return ;
                        }
                        else if(rv.ret == "0"){
                            alert("<%:successfully switch%>");
                            document.getElementById("trunkconfig").style.display="none";//隐藏
                            document.getElementsByName("loadSelect")[0].checked = true;   
                        }
                    }
                   );
        }
    }
    else if(val == "2"){//static
        if(confirm("<%:are you sure you want to switch configuration?%>")){
            //异步提交数据
            XHR.get('<%=REQUEST_URI%>',{"modedisable": "2"}, 
                    function(x,rv) {
                        //        alert(JSON.stringify(rv));
                        if(rv.ret == "-1"){
                            alert("<%:switch failure%>");
                            return ;
                        }
                        else if(rv.ret == "0"){
                            alert("<%:successfully switch%>");
                            document.getElementById("trunkconfig").style.display="";//显
                            // myfun();
                            window.location.reload();
                        }
                    }
                   );
        }
    }
}

function setLoadMode(){
    var loadMode;
    for(i=0;i<document.getElementsByName("loadSelect").length;i++){
        if(document.getElementsByName("loadSelect")[i].checked == true){
            loadMode = document.getElementsByName("loadSelect")[i].value
        }
    }
    XHR.get('<%=REQUEST_URI%>',{ "setLoad": loadMode},
            function(x,rv)
            {
                if(rv.ret == "-1"){
                    alert("<%:Configuration failed%>");
                }else if(rv.ret == "0"){
                    alert("<%:Succesfully configured%>");
                }
            }
           );

}


//添加光标焦点
function addFocus(){
    $('#channel').focus();
}

//验证ID输入
function provID(the){
    var num = parseInt(the.value);
    if(num<=0 || num>15 || isNaN(num)){
        the.focus();
        
        console.log($(the).next())
        $(the).next().attr("style","display:block;color:red");
        $(the).next().html("<%:Please fill in 1~15 integer%>");
        
        the.value=" ";
        return;
    }else{
        the.value=num;
        $(the).next().attr("style","display:none");
            }
}
//只能选择8个
function ck(){
    var chked = $("#myTab input[name^=port]:checked");
    var unChked = $("#myTab input[name^=port]:not(:checked)");
    if (unChked.length <= 8) {
        console.log(1)
    };
   
    if(chked.length==8){
        for(var j=0;j<unChked.length;j++){
            unChked[j].disabled = true;
        }
    }else if(chked.length==7){
        for(var j=0,len=unChked.length;j<len;j++){
            unChked[j].disabled = false;
        }
    }
}
function addNewRow(idVal,memberVal){
    var colsNum = $("#myTab tr:eq(0) th").length;
    var ss = memberVal.split("-");
    var aa = 0;
    if(OCTET_NUM > 1){
        for(var k = 0; k < OCTET_NUM -1; k++){//避免最后一个字节乘0处理
            aa += parseInt(ss[k],16)*256*(OCTET_NUM-1-k);
        }
        aa += parseInt(ss[OCTET_NUM-1],16);
    }else{
        aa = parseInt(ss[OCTET_NUM-1],16);
    }
    var data = shift_fun(OCTET_NUM * 8, aa);
    
    for(var j=1,arr=[];j<colsNum;j++){      
        if(((data >> (j-1)) & 1) == 1){
            var chkObj =  document.getElementById("chkPort"+j);
            arr.push($(chkObj).attr("name"));
            chkObj.disabled = true;
        }
    }

    var tabObj=document.getElementById("myTabList");
    var rowsNum = tabObj.rows.length;
    var myNewRow = tabObj.insertRow(rowsNum);
    myNewRow.insertCell(0).innerHTML = "<input type='checkbox' name='chkArr' id=" +"chkArr"+ rowsNum +" /><input type='text' name='idx' style='width:30px' readonly='true'  value=" + rowsNum + " >";
    myNewRow.insertCell(1).innerHTML = idVal;
    myNewRow.insertCell(2).innerHTML = arr.join();
}

function truJson(){
    var a = JSON.parse("{\"idx\":\"\",\"channel_id\":\"\",\"channel_member\":\"\"}"); 


    a.idx = $("#myTabList tr").length;
    if(a.idx > 8){
        alert("<%:Max trunk group is 8%>");
        return;
    }
    
    a.channel_id = $("#channel").val();
    var tdObj = $("#myTabList tr td:nth-child(2)");
    if (Number(a.channel_id) < 1 || Number(a.channel_id) > 15){ 
        alert("<%:Channel_id need a value input%>");
        return;
    }
    for (var i = 0; i < tdObj.length; i++) {
        if ($(tdObj[i]).text() == a.channel_id) {
            alert("<%:The same trunk id set%>");
            return;
        };
    };

    var memVal = 0;
    var portArr = new Array();
    var len = 0;
    var typeRcve = <%=luci.json.encode(typeStatus)%>;
    for(var j=1;j<=<%=portNum%>;j++){
        if(document.getElementById("chkPort"+j).checked == true){
            memVal |=  1<<(j-1);
            portArr[len] = typeRcve[j-1]["ret"][0]["port-"+j][0]["type"];
            len++; 
        }
    }
    for(var loop = 0; loop < portArr.length; loop++){
        if(portArr[loop] != portArr[0]){
            alert("<%:Cannot set fiber and copper in the same group of trunk id%>");
            return;
        }
    }
    var data = shift_fun(OCTET_NUM * 8,memVal);
    var sda = new Array();
    for(var n = 0; n < OCTET_NUM - 1; n++){
        sda[n] = parseInt((data / (256 * (OCTET_NUM - 1 - n))) % 256).toString(16);
    }
    sda[OCTET_NUM -1] = (data % 256).toString(16);
    
    a.channel_member = sda.join("-");

  
//   alert(JSON.stringify(a));
//   console.log(JSON.stringify(a));
    //异步提交数据
    XHR.get('<%=REQUEST_URI%>',{"param": JSON.stringify(a)}, 
        function(x,rv) {
     //       alert(JSON.stringify(rv));
            if(rv.ret == "0"){
                alert("<%:Succesfully configured%>");
                $("#channel").val(" ");
                $("[id^=chkPort]").each(function(){
                    this.checked = false;
                });
                addNewRow(a.channel_id,a.channel_member);
            }
            else if(rv.ret == "-1"){
                alert("<%:Configuration failed%>");
                window.location.reload();
                return;
            }

        }
    );

}

function removeRow(){
    var chkObj=document.getElementsByName("chkArr");
    var tabObj=document.getElementById("myTabList");
    var a = JSON.parse("{\"idx\":\"\"}"); 

    var rowsNum = tabObj.rows.length;  //获取当前行数

    for(var k=0;k<chkObj.length;k++){
        if(chkObj[k].checked){
            //下发ubus 删除该组信息
            a.idx = k+1;
            //异步提交数据
            XHR.get('<%=REQUEST_URI%>',{ "clear": JSON.stringify(a)},
                    function(x,rv)
                    {
                        if(rv.ret == "-1"){
                            alert("<%:NO.%>"+ a.idx +"<%:configuration failure%>");
                            window.location.reload();
                            return ;
                        }
                        else if(rv.ret == "0"){
                        }
                    }
                   );
            if ($("#myTabList tr:eq("+a.idx+") td:last").text() != ""){
                $($("#myTabList tr:eq("+a.idx+") td:last").text().split(",")).each(function(){
                    $("[name="+this+"]")[0].disabled = false;
                });
            }
            //页面删除行
            tabObj.deleteRow(a.idx);
            k=-1;
        }
    }
    //序号重新排列
    var curRows = tabObj.rows.length;  //获取当前行数
    for(var n=0;n<(curRows-1);n++){
        document.getElementsByName("idx")[n].value = n+1;
    }
    alert("<%:delete success%>");

}
function modVlan(){
    var cheObj = $("#myTabList input:checked");
    if (cheObj.length==0) {
        alert("<%:Choose a group of trunk to modify%>");
        return;
    }else if(cheObj.length>1){
        alert("<%:Does not support batch change, please select a set to modify%>");
        return;
    }else{
        if(confirm("<%:the existing configuration changes, can only be deleted after reconfiguration. Sure you want to continue to modify?%>")){
            addFocus();

            $("#channel").val(cheObj.parent().next().text());
            var menVal = cheObj.parent().next().next().text().split(",");
            if(menVal != ""){
                for (var i = 0; i < menVal.length; i++) {
                    $("[name="+menVal[i]+"]")[0].checked = true;
                }
            }
            removeRow();
        }
    }
}
function display(){
    //显示端口名称
    var typeRcv = <%=luci.json.encode(typeStatus)%>;
    $.each(typeRcv, function(i,val) {
        var rcv = val.ret[0]["port-"+(i+1)];
        if(rcv[0].type == "4"){
            document.getElementById("port"+(i+1)).innerHTML = "G"+(i+1);
            document.getElementById("chkPort"+(i+1)).name = "G"+(i+1);
        }
        else if(rcv[0].type == "2"){
            document.getElementById("port"+(i+1)).innerHTML = "F"+(i+1);
            document.getElementById("chkPort"+(i+1)).name = "F"+(i+1);
        }
        else if(rcv[0].type == "5"){
            document.getElementById("port"+(i+1)).innerHTML = "C"+(i+1);
            document.getElementById("chkPort"+(i+1)).name = "C"+(i+1);
        }
    });
    //显示mode_select的值
    var m = document.getElementById("trunkMode");
    var mode_val = '<%=modeVal%>';
    m.selectedIndex = mode_val-1;
    document.getElementById("trunkconfig").style.display = (mode_val == "2") ?"":"none";

    //显示负载平衡的值
    var load_val = '<%=balVal%>';
    $("input[name=loadSelect][value="+load_val+"]")[0].checked = true;

    var rcv = <%=luci.json.encode(status)%>;
    // console.log(rcv)
    var chan_val = '<%=chanVal%>';
    for(n=1;n<=Number(chan_val);n++){
        var idVal = rcv[n-1]["ret"][0]["idx-"+n][0].channel_id;
        var memberVal = rcv[n-1]["ret"][0]["idx-"+n][1].channel_member;
  
        addNewRow(idVal,memberVal);
    }
}

window.onload=display;


</script>


<div class="trunk" >
    <h3 class="h3"><%:Port aggregation configuration%></h3>
    <!--<div class = "cbi-map-descr">
        <%:将由相同属性配置的一组端口抽象成一个逻辑端口来增加带宽，提高传输速率，统一据合组中各成员端口实现流量分担，并且彼此之间动态备份，提高连接的可靠性%>
    </div>
     <form action = '<%=luci.dispatcher.build_url("admin/ethernet/trunk_config/trunk_set")%>'  method = "get"> -->
        <fieldset class="trunk-section"> <!-- <fieldset> 标签可以将表单内的相关元素分组 -->
            <legend><%:Port aggregation mode selection%></legend>
            <table class="">
                <tr>
                    <th style="text-align: left">
                        <%:Aggregation mode :%>&nbsp; &nbsp; &nbsp;
                        <select name = "aggrMode" id="trunkMode" onchange="modeSelect()">
                            <option  value = "1"><%:Disable%></option>
                            <option  value = "2"><%:static%></option>
                        </select>
                    </th>
                </tr>
            </table>
        </fieldset>

        <div class="trunk"  id = "trunkconfig" style="display: none;" >
            <fieldset class=""> <!-- <fieldset> 标签可以将表单内的相关元素分组 -->
            <legend><%:Port load balance mode selection%></legend>
                <table class="miniTab">
                    <tr>
                        <th><%:load balance :%></th>
                        <td>
                            <input type="radio" name="loadSelect" value="1" checked = true/>xor&nbsp;&nbsp;&nbsp;
                            <input type="radio" name="loadSelect" value="2" />hash
                        </td>
                    </tr>
                    <tfoot>
                        <tr>
                            <td colspan="2">
                                <input type="button" name="ok" value="<%:Apply%>" class="cbi-button cbi-input-apply" onclick="setLoadMode()" />
                            </td>
                        </tr>
                    </tfoot>      
                </table>

            </fieldset>
            <fieldset class=""> <!-- <fieldset> 标签可以将表单内的相关元素分组 -->
                <legend><%:aggregation group%></legend>
                    <table id = "myTabList" >
                        <tr>
                            <th><%:serial number%></th>
                            <th><%:aggregation group ID%></th>
                            <th><%:member%></th>
                        </tr>
                    </table>

                    <div class="cbi-button-grow">
                        <input type="button" name="add" value="<%:Add%>" class="cbi-button cbi-button-add" onclick="addFocus()"/>
                        <input type="button" name="ok" value="<%:Edit%>" class="cbi-button cbi-input-remove" onclick="modVlan()">
                        <input type="button" name="del" value="<%:Delete%>" class="cbi-button cbi-button-remove" onclick="removeRow()"/>
                    </div>
                <legend><%:aggregation group configuration%></legend>
                <!-- <div class="trunk-section-table"> -->
                    <table id = "myTab" >
                         <tr>
                             <th style="width:12%"><%:aggregation group ID%></th>
                            <% for i=1, portNum do%>
                            <th id = "port<%=i%>"><%=i%></th>
                            <% end %>
                         </tr>   

                         <tr>
                            <td>
                                <input type="text" id="channel" style="width:4rem;text-align:center;" value="" onblur="provID(this)">
                                <p style="color: red;padding-top: 4px;font-size: 0.8rem;display: none"></p>
                            </td>
                            <% for i=1, portNum do%>
                            <td><input type="checkbox" name="port<%=i%>" id="chkPort<%=i%>" onclick="ck()"></td>
                            <% end %>
                         </tr>
                    </table>
                    <div class="cbi-button-grow">
                        <input type="button" name="ok" value="<%:Apply%>" class="cbi-button cbi-input-apply" onclick="truJson()" />
                    </div>
                <!-- </div> -->
                    
            </fieldset>
        </div>
    <!-- </form> -->
</div>

<%+footer%>












